(function($) {
	$.fn.ajaxSubmit = function(options) {
		if (typeof options == "function") {
			options = {
				success : options
			}
		}
		options = $.extend( {
			url : this.attr("action") || window.location.toString(),
			type : this.attr("method") || "GET"
		}, options || {});
		var veto = {};
		$.event.trigger("form.pre.serialize", [ this, options, veto ]);
		if (veto.veto) {
			return this
		}
		var a = this.formToArray(options.semantic);
		if (options.data) {
			for ( var n in options.data) {
				a.push( {
					name : n,
					value : options.data[n]
				})
			}
		}
	
		if (options.beforeSubmit
				&& options.beforeSubmit(a, this, options) === false) {
			return this
		}
		$.event.trigger("form.submit.validate", [ a, this, options, veto ]);
		if (veto.veto) {
			return this
		}
		var q = $.param(a);
		if (options.type.toUpperCase() == "GET") {
			options.url += (options.url.indexOf("?") >= 0 ? "&" : "?") + q;
			options.data = null
		} else {
			options.data = q
		}
		var $form = this, callbacks = [];
		if (options.resetForm) {
			callbacks.push(function() {
				$form.resetForm()
			})
		}
		if (options.clearForm) {
			callbacks.push(function() {
				$form.clearForm()
			})
		}
		if (!options.dataType && options.target) {
			var oldSuccess = options.success || function() {
			};
			callbacks.push(function(data) {
				if (this.evalScripts) {
					$(options.target).attr("innerHTML", data).evalScripts()
							.each(oldSuccess, arguments)
				} else {
					$(options.target).html(data).each(oldSuccess, arguments)
				}
			})
		} else {
			if (options.success) {
				callbacks.push(options.success)
			}
		}
		options.success = function(data, status) {
			for ( var i = 0, max = callbacks.length; i < max; i++) {
				callbacks[i](data, status, $form)
			}
		};
		var files = $("input:file", this).fieldValue();
		var found = false;
		for ( var j = 0; j < files.length; j++) {
			if (files[j]) {
				found = true
			}
		}
		if (options.iframe || found) {
			if (BrowserDetect.browser="Safari" && options.closeKeepAlive) {
				$.get(options.closeKeepAlive, fileUpload)
			} else {
				fileUpload()
			}
		} else {
			$.ajax(options)
		}
		$.event.trigger("form.submit.notify", [ this, options ]);
		return this;
		function fileUpload() {
			var form = $form[0];
			var opts = $.extend( {}, $.ajaxSettings, options);
			var id = "jqFormIO" + $.fn.ajaxSubmit.counter++;
			var $io = $('<iframe id="' + id + '" name="' + id + '" />');
			var io = $io[0];
			var op8 = BrowserDetect.browser="window.opera" && BrowserDetect.version < 9; //这个没试验过  不知道对不对,暂时没有用opear浏览器
			if (BrowserDetect.browser="Explorer" || op8) {
				io.src = 'javascript:false;document.write("");'
			}
			$io.css( {
				position : "absolute",
				top : "-1000px",
				left : "-1000px"
			});
			var xhr = {
				responseText : null,
				responseXML : null,
				status : 0,
				statusText : "n/a",
				getAllResponseHeaders : function() {
				},
				getResponseHeader : function() {
				},
				setRequestHeader : function() {
				}
			};
			var g = opts.global;
			if (g && !$.active++) {
				$.event.trigger("ajaxStart")
			}
			if (g) {
				$.event.trigger("ajaxSend", [ xhr, opts ])
			}
			var cbInvoked = 0;
			var timedOut = 0;
			setTimeout(function() {
				var encAttr = form.encoding ? "encoding" : "enctype";
				var t = $form.attr("target");
				$form.attr( {
					target : id,
					method : "POST",
					action : opts.url
				});
				form[encAttr] = "multipart/form-data";
				if (opts.timeout) {
					setTimeout(function() {
						timedOut = true;
						cb()
					}, opts.timeout)
				}
				$io.appendTo("body");
				io.attachEvent ? io.attachEvent("onload", cb) : io
						.addEventListener("load", cb, false);
				form.submit();
				$form.attr("target", t)
			}, 10);
			function cb() {
				if (cbInvoked++) {
					return
				}
				io.detachEvent ? io.detachEvent("onload", cb) : io
						.removeEventListener("load", cb, false);
				var ok = true;
				try {
					if (timedOut) {
						throw "timeout"
					}
					var data, doc;
					doc = io.contentWindow ? io.contentWindow.document
							: io.contentDocument ? io.contentDocument
									: io.document;
					xhr.responseText = doc.body ? doc.body.innerHTML : null;
					xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
					if (opts.dataType == "json" || opts.dataType == "script") {
						var ta = doc.getElementsByTagName("textarea")[0];
						data = ta ? ta.value : xhr.responseText;
						if (opts.dataType == "json") {
							eval("data = " + data)
						} else {
							$.globalEval(data)
						}
					} else {
						if (opts.dataType == "xml") {
							data = xhr.responseXML;
							if (!data && xhr.responseText != null) {
								data = toXml(xhr.responseText)
							}
						} else {
							data = xhr.responseText
						}
					}
				} catch (e) {
					ok = false;
					$.handleError(opts, xhr, "error", e)
				}
				if (ok) {
					opts.success(data, "success");
					if (g) {
						$.event.trigger("ajaxSuccess", [ xhr, opts ])
					}
				}
				if (g) {
					$.event.trigger("ajaxComplete", [ xhr, opts ])
				}
				if (g && !--$.active) {
					$.event.trigger("ajaxStop")
				}
				if (opts.complete) {
					opts.complete(xhr, ok ? "success" : "error")
				}
				setTimeout(function() {
					$io.remove();
					xhr.responseXML = null
				}, 100)
			}
			function toXml(s, doc) {
				if (window.ActiveXObject) {
					doc = new ActiveXObject("Microsoft.XMLDOM");
					doc.async = "false";
					doc.loadXML(s)
				} else {
					doc = (new DOMParser()).parseFromString(s, "text/xml")
				}
				return (doc && doc.documentElement && doc.documentElement.tagName != "parsererror") ? doc
						: null
			}
		}
	};
	$.fn.ajaxSubmit.counter = 0;
	$.fn.ajaxForm = function(options) {
		return this.ajaxFormUnbind().submit(submitHandler).each(function() {
			this.formPluginId = $.fn.ajaxForm.counter++;
			$.fn.ajaxForm.optionHash[this.formPluginId] = options;
			$(":submit,input:image", this).click(clickHandler)
		})
	};
	$.fn.ajaxForm.counter = 1;
	$.fn.ajaxForm.optionHash = {};
	function clickHandler(e) {
		var $form = this.form;
		$form.clk = this;
		if (this.type == "image") {
			if (e.offsetX != undefined) {
				$form.clk_x = e.offsetX;
				$form.clk_y = e.offsetY
			} else {
				if (typeof $.fn.offset == "function") {
					var offset = $(this).offset();
					$form.clk_x = e.pageX - offset.left;
					$form.clk_y = e.pageY - offset.top
				} else {
					$form.clk_x = e.pageX - this.offsetLeft;
					$form.clk_y = e.pageY - this.offsetTop
				}
			}
		}
		setTimeout(function() {
			$form.clk = $form.clk_x = $form.clk_y = null
		}, 10)
	}
	function submitHandler() {
		var id = this.formPluginId;
		var options = $.fn.ajaxForm.optionHash[id];
		$(this).ajaxSubmit(options);
		return false
	}
	$.fn.ajaxFormUnbind = function() {
		this.unbind("submit", submitHandler);
		return this.each(function() {
			$(":submit,input:image", this).unbind("click", clickHandler)
		})
	};
	$.fn.formToArray = function(semantic) {
		var a = [];
		if (this.length == 0) {
			return a
		}
		var form = this[0];
		var els = semantic ? form.getElementsByTagName("*") : form.elements;
		if (!els) {
			return a
		}
		for ( var i = 0, max = els.length; i < max; i++) {
			var el = els[i];
			var n = el.name;
			if (!n) {
				continue
			}
			if (semantic && form.clk && el.type == "image") {
				if (!el.disabled && form.clk == el) {
					a.push( {
						name : n + ".x",
						value : form.clk_x
					}, {
						name : n + ".y",
						value : form.clk_y
					})
				}
				continue
			}
			var v = $.fieldValue(el, true);
			if (v && v.constructor == Array) {
				for ( var j = 0, jmax = v.length; j < jmax; j++) {
					a.push( {
						name : n,
						value : v[j]
					})
				}
			} else {
				if (v !== null && typeof v != "undefined") {
					a.push( {
						name : n,
						value : v
					})
				}
			}
		}
		if (!semantic && form.clk) {
			var inputs = form.getElementsByTagName("input");
			for ( var i = 0, max = inputs.length; i < max; i++) {
				var input = inputs[i];
				var n = input.name;
				if (n && !input.disabled && input.type == "image"
						&& form.clk == input) {
					a.push( {
						name : n + ".x",
						value : form.clk_x
					}, {
						name : n + ".y",
						value : form.clk_y
					})
				}
			}
		}
		return a
	};
	$.fn.formSerialize = function(semantic) {
		return $.param(this.formToArray(semantic))
	};
	$.fn.fieldSerialize = function(successful) {
		var a = [];
		this.each(function() {
			var n = this.name;
			if (!n) {
				return
			}
			var v = $.fieldValue(this, successful);
			if (v && v.constructor == Array) {
				for ( var i = 0, max = v.length; i < max; i++) {
					a.push( {
						name : n,
						value : v[i]
					})
				}
			} else {
				if (v !== null && typeof v != "undefined") {
					a.push( {
						name : this.name,
						value : v
					})
				}
			}
		});
		return $.param(a)
	};
	$.fn.fieldValue = function(successful) {
		for ( var val = [], i = 0, max = this.length; i < max; i++) {
			var el = this[i];
			var v = $.fieldValue(el, successful);
			if (v === null || typeof v == "undefined"
					|| (v.constructor == Array && !v.length)) {
				continue
			}
			v.constructor == Array ? $.merge(val, v) : val.push(v)
		}
		return val
	};
	$.fieldValue = function(el, successful) {
		var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
		if (typeof successful == "undefined") {
			successful = true
		}
		if (successful
				&& (!n || el.disabled || t == "reset" || t == "button"
						|| (t == "checkbox" || t == "radio") && !el.checked
						|| (t == "submit" || t == "image") && el.form
						&& el.form.clk != el || tag == "select"
						&& el.selectedIndex == -1)) {
			return null
		}
		if (tag == "select") {
			var index = el.selectedIndex;
			if (index < 0) {
				return null
			}
			var a = [], ops = el.options;
			var one = (t == "select-one");
			var max = (one ? index + 1 : ops.length);
			for ( var i = (one ? index : 0); i < max; i++) {
				var op = ops[i];
				if (op.selected) {
					var v = BrowserDetect.browser="Explorer" && !(op.attributes.value.specified) ? op.text   //原来是用$.browser.msie判断的,但是jquery1.9后移除了这个方法
							: op.value;
					if (one) {
						return v
					}
					a.push(v)
				}
			}
			return a
		}
		return el.value
	};
	$.fn.clearForm = function() {
		return this.each(function() {
			$("input,select,textarea", this).clearFields()
		})
	};
	$.fn.clearFields = $.fn.clearInputs = function() {
		return this.each(function() {
			var t = this.type, tag = this.tagName.toLowerCase();
			if (t == "text" || t == "password" || tag == "textarea") {
				this.value = ""
			} else {
				if (t == "checkbox" || t == "radio") {
					this.checked = false
				} else {
					if (tag == "select") {
						this.selectedIndex = -1
					}
				}
			}
		})
	};
	$.fn.resetForm = function() {
		return this
				.each(function() {
					if (typeof this.reset == "function"
							|| (typeof this.reset == "object" && !this.reset.nodeType)) {
						this.reset()
					}
				})
	};
	$.fn.enable = function(b) {
		if (b == undefined) {
			b = true
		}
		return this.each(function() {
			this.disabled = !b
		})
	};
	$.fn.select = function(select) {
		if (select == undefined) {
			select = true
		}
		return this.each(function() {
			var t = this.type;
			if (t == "checkbox" || t == "radio") {
				this.checked = select
			} else {
				if (this.tagName.toLowerCase() == "option") {
					var $sel = $(this).parent("select");
					if (select && $sel[0] && $sel[0].type == "select-one") {
						$sel.find("option").select(false)
					}
					this.selected = select
				}
			}
		})
	}
})(jQuery);